[SpringBoot] パッケージが異なるクラスを @Autowired する
はじめに
SpringBoot楽しいですよね。
クラスを作って@Componentを書いて、@Autowireでメンバーに注入する。なんて楽にかけるんだ!!と思っていたのですが、少しクラス数も多くなってきたのでパッケージを分けてみたら
org.springframework.beans.factory.NoSuchBeanDefinitionException
とエラーが返ってきたので回避方法を調べました。
環境
Spring Tool Suite 3.8.0
失敗したコード
うまくいかなかったコードがこんな感じです。かなり簡略化はしています。
├ com.example/ │ ├ SpringBootPracticeApplication │ └ BatchProcessing └ nextPackage/ └ Hoge
package com.example; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; import nextPackage.Hoge; @SpringBootApplication @EnableScheduling public class SpringBootPracticeApplication { public static void main(String[] args) { SpringApplication.run(SpringBootPracticeApplication.class, args); } }
@EnableSchedulingと下の@Scheduledは定期実行するために必要なアノテーションになります。興味のある方はこちらをどうぞ!
package com.example; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import nextPackage.Hoge; @Service public class BatchProcessing { @Autowired Hoge hoge; @Scheduled(fixedDelay = 5000) public void fixedRate(){ System.out.println(hoge.getHoge()); } }
ちゃんとimportもしているのになんで?
package nextPackage; import org.springframework.context.annotation.ComponentScan; import org.springframework.stereotype.Component; @Component public class Hoge { public String getHoge(){ return "hoge"; } }
上のコードは単純に5秒おきにgetHogeで返される文字列を表示するだけのものです。
回避方法
答えとしては非常に簡単で
@Service @ComponentScan("nextPackage") public class BatchProcessing { @Autowired Hoge hoge; @Scheduled(fixedDelay = 5000) public void fixedRate(){ System.out.println(hoge.getHoge()); } }
パッケージ外はScanしてないから明示的に指定する必要があるようですね。 @ComponentScan("")で指定することによって解決しました。
他にも@Autowiredするクラスを同一パッケージにする方法なんかもあるようです。
最後に
何通りか方法はあるようですが、パッケージ構成を変えてまでやるほどのことでもないので@ComponentScan("")を使うのが現実的ではないかなと思いました。
参考
https://teratail.com/questions/4532